From 98cb2ef79728bc2270b13d46492af03839ccbed5 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 11 Nov 2008 11:47:03 +0000 Subject: [PATCH] hvm: fix single stepping on debugger The debuggee domain will die with unexpected trap on single stepping of emulated instruction. Signed-off-by: Kouya Shimura Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/svm/svm.c | 24 +++++++++++++++++------- xen/arch/x86/hvm/vmx/realmode.c | 20 ++++++++++++++------ xen/arch/x86/hvm/vmx/vmx.c | 25 ++++++++++++++++++------- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index c635f5204a..499cd619d4 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -739,6 +739,23 @@ static void svm_inject_exception( struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb; eventinj_t event = vmcb->eventinj; + switch ( trapnr ) + { + case TRAP_debug: + if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF ) + { + __restore_debug_registers(curr); + vmcb->dr6 |= 0x4000; + } + case TRAP_int3: + if ( curr->domain->debugger_attached ) + { + /* Debug/Int3: Trap to debugger. */ + domain_pause_for_debugger(); + return; + } + } + if ( unlikely(event.fields.v) && (event.fields.type == X86_EVENTTYPE_HW_EXCEPTION) ) { @@ -765,13 +782,6 @@ static void svm_inject_exception( { HVMTRACE_2D(INJ_EXC, trapnr, errcode); } - - if ( (trapnr == TRAP_debug) && - (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) ) - { - __restore_debug_registers(curr); - vmcb->dr6 |= 0x4000; - } } static int svm_event_pending(struct vcpu *v) diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c index b067eb1615..4af2848406 100644 --- a/xen/arch/x86/hvm/vmx/realmode.c +++ b/xen/arch/x86/hvm/vmx/realmode.c @@ -149,17 +149,25 @@ static void realmode_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt) hvmemul_ctxt->exn_insn_len = 0; } - if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) + if ( unlikely(curr->domain->debugger_attached) && + ((hvmemul_ctxt->exn_vector == TRAP_debug) || + (hvmemul_ctxt->exn_vector == TRAP_int3)) ) + { + domain_pause_for_debugger(); + } + else if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) { gdprintk(XENLOG_ERR, "Exception %02x in protected mode.\n", hvmemul_ctxt->exn_vector); goto fail; } - - realmode_deliver_exception( - hvmemul_ctxt->exn_vector, - hvmemul_ctxt->exn_insn_len, - hvmemul_ctxt); + else + { + realmode_deliver_exception( + hvmemul_ctxt->exn_vector, + hvmemul_ctxt->exn_insn_len, + hvmemul_ctxt); + } } return; diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 801b6da347..4156f02ad1 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1118,6 +1118,24 @@ static void __vmx_inject_exception(int trap, int type, int error_code) void vmx_inject_hw_exception(int trap, int error_code) { unsigned long intr_info = __vmread(VM_ENTRY_INTR_INFO); + struct vcpu *curr = current; + + switch ( trap ) + { + case TRAP_debug: + if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF ) + { + __restore_debug_registers(curr); + write_debugreg(6, read_debugreg(6) | 0x4000); + } + case TRAP_int3: + if ( curr->domain->debugger_attached ) + { + /* Debug/Int3: Trap to debugger. */ + domain_pause_for_debugger(); + return; + } + } if ( unlikely(intr_info & INTR_INFO_VALID_MASK) && (((intr_info >> 8) & 7) == X86_EVENTTYPE_HW_EXCEPTION) ) @@ -1134,13 +1152,6 @@ void vmx_inject_hw_exception(int trap, int error_code) TRC_PAR_LONG(current->arch.hvm_vcpu.guest_cr[2])); else HVMTRACE_2D(INJ_EXC, trap, error_code); - - if ( (trap == TRAP_debug) && - (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) ) - { - __restore_debug_registers(current); - write_debugreg(6, read_debugreg(6) | 0x4000); - } } void vmx_inject_extint(int trap) -- 2.30.2